package server.data;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import server.AuctionManager;

/**
 * Represents a single Auction
 * @author Andreas
 */
public class Auction 
{
	private static long lMaxId=1;
	
	private final long lId;
	private final Date dEnd;
	private final String strDesc;
        private Bid highestBid;
	private final User uOwner;
        private Map<String,GroupBid> groupBids;
        private int countGroupBids; //counts all tentative or finished groupBids (cancelled GroupBids don't count)

	/**
	* Constructor
	*/
	public Auction(final long lTime, final String strDesc, final User uOwner) 
	{
            super();
            this.lId = lMaxId++;
            this.dEnd=new Date(System.currentTimeMillis()+lTime*1000);
            this.strDesc = strDesc;
            this.uOwner = uOwner;
            this.groupBids=new HashMap<String,GroupBid>();
            this.countGroupBids=0;
	}

	/*
	 * Getters & Setters
	 */
	public long getlId() 
	{
            return lId;
	}
	
	public Date getdEnd()
	{
            return dEnd;
	}

	public String getStrDesc() 
	{
            return strDesc;
	}

	public Bid getHighestBid() 
	{
            return this.highestBid;
	}

	public void setHighestBid(final Bid highest) 
	{
            this.highestBid= highest;
	}

	public User getuOwner() 
	{
            return uOwner;
	}
	
	
	/*
	 * (non-Javadoc) @see java.lang.Object#toString(java.lang.Object)
	 */
	@Override
	public String toString()
	{
		String strHighest="none";
                double dPrice=0;
		if(this.highestBid!=null)
		{
			strHighest=highestBid.getBidder().getStrName();
                        dPrice=highestBid.getdPrice();
		}
		AuctionManager am=AuctionManager.getInstance();
                StringBuilder strB=new StringBuilder(40);
                strB.append(lId).append(". '").append(strDesc).append("' ").append(uOwner.getStrName()).append(" ").append(am.formatDate(dEnd)).append(" ").append(am.formatDouble(dPrice)).append(" ").append(strHighest);
		return strB.toString();
                //return this.lId+". '"+this.strDesc+"' "+this.uOwner.getStrName()+" "+am.formatDate(dEnd)+" "+am.formatDouble(dPrice)+" "+strHighest;
	}
        
        /**
         * Checks if the auction gets overbid by a bid
         * @param bid
         * @return true if bid is greater than the highest bid (or if there was no bid before)
         */
        public boolean overbidBy(final Bid bid)
        {
            boolean bRet=false;
            if(this.highestBid==null || this.highestBid.smallerThan(bid))
            {
                bRet=true;
            }
            return bRet;
        }
        
        /**
         * Adds a new GroupBid to the Auction
         * @param bid
         * @return false if the groupbid does already exist with the same amount from the same user
         */
        public boolean addGroupBid(final GroupBid bid)
        {
            boolean bRet=false;
            final String strBid=bid.toString();
            if(!this.groupBids.containsKey(strBid))
            {
                this.groupBids.put(strBid, bid);
                this.countGroupBids++;
                bRet=true;
            }
            return bRet;
        }
        
        /**
         * Removes a GroupBid from the Auction
         * @param bid
         */
        public void removeGroupBid(final GroupBid bid)
        {
            final String strBid=bid.toString();
           if(this.groupBids.containsKey(strBid))
           {
               if(!bid.isFinished())
               {
                   countGroupBids--;
               }
               this.groupBids.remove(strBid);
           }
        }
        
        public boolean hasGroupBid()
        {
            return countGroupBids>0;
        }
        
        /**
         * Returns the GroupBid identified by strKey if it exists
         * @param strKey
         * @return GroupBid identified by strKey if it exists otherwise null
         */
        public GroupBid getGroupBid(String strKey)
        {
            return this.groupBids.get(strKey);
        }
        
        /**
         * Checks if Auction is finished (if dEnd>System.currentTimeInMillis)
         * @return true if Auction is finished
         */
        public boolean isFinished()
        {
            return this.dEnd.getTime()<System.currentTimeMillis();
        }
}
